package cn.scau.server.service.impl;

import cn.scau.server.pojo.ApplicationItems;
import cn.scau.server.pojo.ProcessInfo;
import cn.scau.server.mapper.ProcessInfoMapper;
import cn.scau.server.pojo.ProcessNode;
import cn.scau.server.service.ApplicationItemsService;
import cn.scau.server.service.ProcessInfoService;
import cn.scau.server.service.ProcessNodeService;
import cn.scau.server.dto.ProcessDetailDTO;
import cn.scau.server.vo.ResultVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 代码不跑我先跑
 * @since 2025-03-30
 */
@Service
@Transactional
public class ProcessInfoServiceImpl extends ServiceImpl<ProcessInfoMapper, ProcessInfo> implements ProcessInfoService {

    @Autowired
    private ApplicationItemsService applicationItemsService;

    @Autowired
    private ProcessNodeService processNodeService;

    @Override
    public ResultVO addProcess(String typeName, List<String> processItems, List<ProcessNode> processNodes) {
        //1.先判断typeName是不是空的
        if(typeName.isEmpty()||typeName==null){
            return ResultVO.fail("流程类型不能为空");
        }
        //2.将typeName存入数据库中，并得到存好的typeId
        ProcessInfo processInfo = new ProcessInfo();
        processInfo.setFlowType(typeName);
        processInfo.setUsing(true);
        boolean saveProcessInfo = save(processInfo);
        if(!saveProcessInfo){
            return ResultVO.fail("存入流程类型失败！");
        }
        Integer processId = processInfo.getId();
        //2.将申请项挨个放入数据库中
        processItems.stream().forEach(item->{
            ApplicationItems applicationItems = new ApplicationItems();
            applicationItems.setItemName(item);
            applicationItems.setFlowId(processId);
            boolean saveItem = applicationItemsService.save(applicationItems);
            if(!saveItem){
                log.error("存入申请项:"+item+"失败！");
            }
        });
        //3.将节点挨个放在数据库中
        // 创建被撤销状态ProcessNode 对象
        ProcessNode node1 = new ProcessNode();
        node1.setNodeName("已撤销");
        node1.setNodePriority(-1);
        node1.setIsWithDept(false);
        node1.setDeptPriority(-1);
        node1.setFlowId(processId);

        // 创建被驳回ProcessNode 对象
        ProcessNode node2 = new ProcessNode();
        node2.setNodeName("已被驳回");
        node2.setNodePriority(-2);
        node2.setIsWithDept(false);
        node2.setDeptPriority(-1);
        node2.setFlowId(processId);
        processNodes.add(node1);
        processNodes.add(node2);

        processNodes.stream().forEach(item->{
            ProcessNode processNode = new ProcessNode();
            processNode.setFlowId(processId);
            processNode.setNodeName(item.getNodeName());
            processNode.setNodePriority(item.getNodePriority());
            processNode.setIsWithDept(item.getIsWithDept());
            if(!item.getIsWithDept()){
                processNode.setDeptPriority(-1);
            }else{
                processNode.setDeptPriority(item.getDeptPriority());
            }
            boolean saveNode = processNodeService.save(processNode);
            if(!saveNode){
                log.error("存入节点:"+item.getNodeName()+"失败！");
            }
        });
        //4.返回成功结果
        return ResultVO.success("存入成功！");
    }

    @Override
    public ResultVO getProcessTypeList() {
        //之后有机会再做滚动分页查询
        QueryWrapper<ProcessInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_using", true);
        List<ProcessInfo> processInfos = list(queryWrapper);
        if(processInfos.isEmpty()){
            return ResultVO.fail("数据库中为空");
        }
        return ResultVO.success("获取类型基本信息成功",processInfos);
    }

    @Override
    public ResultVO getProcessDetail(Integer processId) {
        QueryWrapper<ProcessInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", processId);
        ProcessInfo processInfo = getOne(queryWrapper);
        if(!processInfo.isUsing()){
            return ResultVO.fail("此类型已被禁用");
        }

        ProcessDetailDTO processDetailVO = getProcessDetailVO(processId);
        if(processDetailVO==null){
            return ResultVO.fail("该类型不存在");
        }
        //获取此类型的名称
        String typeName = getProcessName(processId);
        if(typeName==null){
            return ResultVO.fail("此类型不存在！");
        }
        processDetailVO.setProcessType(typeName);
        processDetailVO.setId(processId);
        //发送
        return ResultVO.success("查询成功！",processDetailVO);
    }

    private ProcessDetailDTO getProcessDetailVO(Integer processId) {
        //1.1根据传来的processId，把类型对应的节点拿过来
        List<ProcessNode> processNodes = processNodeService.getByFlowId(processId);
        if(processNodes.isEmpty()){
            return null;
        }
        //1.2按节点优先级排序
        processNodes.sort(Comparator.comparingInt(ProcessNode::getNodePriority));
        //2.收集类型对应的审批项
        List<ApplicationItems> applicationItems = applicationItemsService.getByFlowId(processId);
        if(applicationItems.isEmpty()){
            return null;
        }

        //3.打包到ProcessDetailVO中
        ProcessDetailDTO processDetailVO = new ProcessDetailDTO();
        processDetailVO.setProcessNodes(processNodes);
        processDetailVO.setApplicationItems(applicationItems);

        //4.返回
        return processDetailVO;
    }

    private String getProcessName(Integer processId) {
        QueryWrapper<ProcessInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", processId);
        ProcessInfo processInfo = getOne(queryWrapper);
        if(processInfo==null){
            return null;
        }
        return processInfo.getFlowType();
    }

    @Override
    public String getProcessNameById(Integer processId) {
        QueryWrapper<ProcessInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", processId);
        ProcessInfo processInfo = getOne(queryWrapper);
        if(processInfo==null){
            return null;
        }
        return processInfo.getFlowType();
    }

    @Override
    public ResultVO updateProcessDetail(String processType, List<String> processItems, List<ProcessNode> processNodes) {
        Integer processId = getIdByProcessName(processType);
        if (processId == null) {
            return ResultVO.fail("该类型不存在!");
        }

        ProcessDetailDTO processDetailVO = getProcessDetailVO(processId);
        if (processDetailVO == null) {
            return ResultVO.fail("该类型不存在!");
        }

        List<ProcessNode> existingNodes = processDetailVO.getProcessNodes();
        List<ApplicationItems> existingItems = processDetailVO.getApplicationItems();

        // 处理节点更新
        handleNodeUpdates(processId, existingNodes, processNodes);

        // 处理审批项更新
        handleItemUpdates(processId, existingItems, processItems);

        return ResultVO.success("更新完成");
    }

    private void handleNodeUpdates(Integer processId, List<ProcessNode> existingNodes, List<ProcessNode> newNodes) {
        // 删除不再存在的节点（排除优先级为0的节点）
        existingNodes.stream()
                .filter(node -> node.getNodePriority() > 0)
                .filter(node -> newNodes.stream().noneMatch(n ->
                        n.getNodePriority().equals(node.getNodePriority()) &&
                                n.getNodeName().equals(node.getNodeName())))
                .forEach(node -> {
                    boolean success = processNodeService.removeById(node.getId());
                    if (!success) {
                        log.error("节点删除失败");
                    }
                });

        // 新增或更新节点
        newNodes.forEach(newNode -> {
            Optional<ProcessNode> existingNodeOpt = existingNodes.stream()
                    .filter(n -> n.getNodePriority().equals(newNode.getNodePriority()))
                    .findFirst();

            if (existingNodeOpt.isPresent()) {
                // 更新现有节点
                ProcessNode existingNode = existingNodeOpt.get();
                existingNode.setNodeName(newNode.getNodeName());
                // 可以添加其他需要更新的字段
                boolean success = processNodeService.updateById(existingNode);
                if (!success) {
                    log.error("节点更新失败");
                }
            } else {
                // 新增节点
                newNode.setFlowId(processId);
                boolean success = processNodeService.save(newNode);
                if (!success) {
                    log.error("节点新增失败");
                }
            }
        });
    }

    private void handleItemUpdates(Integer processId, List<ApplicationItems> existingItems, List<String> newItems) {
        // 删除不再存在的审批项
        existingItems.stream()
                .filter(item -> !newItems.contains(item.getItemName()))
                .forEach(item -> {
                    boolean success = applicationItemsService.removeById(item.getId());
                    if (!success) {
                        log.error("审批项删除失败");
                    }
                });

        // 新增不存在的审批项
        newItems.stream()
                .filter(itemName -> existingItems.stream().noneMatch(item -> itemName.equals(item.getItemName())))
                .forEach(itemName -> {
                    ApplicationItems newItem = new ApplicationItems();
                    newItem.setItemName(itemName);
                    newItem.setFlowId(processId);
                    boolean success = applicationItemsService.save(newItem);
                    if (!success) {
                        log.error("审批项新增失败");
                    }
                });
    }

    private Integer getIdByProcessName(String processType) {
        QueryWrapper<ProcessInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flow_type", processType);
        queryWrapper.eq("is_using", true);
        ProcessInfo processInfo = getOne(queryWrapper);
        if(processInfo==null){
            return null;
        }
        return processInfo.getId();
    }

    @Override
    public ResultVO deleteProcessType(Integer processId) {
        //更新被使用状态
        UpdateWrapper<ProcessInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",processId);
        updateWrapper.set("is_using",false);
        boolean update = update(updateWrapper);
        if(!update){
            return ResultVO.fail("删除失败");
        }
        return ResultVO.success("删除成功！");
    }
}
